#!/bin/bash
##########################################################################
# simple-backup.sh
# A simple rsync/ hardlink backup script.
# 
# Copyright (c) 2010 Alexander Metzner <alexander.metzner@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##########################################################################

# Issues the banner to the user
function banner () {
    echo "$0 0.1"
    echo "A simple rsync/ hardlink backup script."
    echo "Copyright (c) 2010 Alexander Metzner <alexander.metzner@gmail.com>."
    echo
    echo "Published under the terms of the Apache License 2.0"
    echo
}

# Reports the error given as $1 and exits the program with error code $2
function error () {
    echo "$0: $1" >&2
	if [ -n "$3" ];
	then
		usage
	fi
    exit $2
}

# Prints the usage to the user
function usage () {
    echo "Usage: $0 [-c] [-q] [-h] [-i ignore_pattern] [-i ignore_file] source target"
    echo "  -c: Compress transmission"
    echo "  -q: Quiet"
	echo "  -i: Ignore files matching the given pattern"
	echo "  -f: Use given list as ignore file list"
    echo "  -h: Issue this help."
}

# Issue an info message to the user
function info () {
    if [ ! $quiet ];
    then
        echo $1
    fi
}

##########################################################################

# Parse command line options
#while getopts s:t:cqh opt
while getopts cqhi:f: opt
do
  case $opt in
    c) compress=1;;
    q) quiet=1;;
	i) ignore=$OPTARG;;
	f) ignore_file=$OPTARG;;
    h) usage; exit 1;;
  esac
done

shift $(($OPTIND-1))

source=$1
target=$2

# Check source
if [ -z "$source" ];
then
    error "Missing source directory." 2 "yes"
fi

# Check target
if [ -z "$target" ];
then
    error "Missing target directory." 3 "yes"
fi

if [ ! -d $target ];
then
    error "$target: not a valid target directory." 4
fi

# Greetings, earthlings
if [ ! $quiet ];
then
    banner
fi

# This is where we store the new snapshot
timestamp=$(date "+%Y-%m-%d-%H-%M-%S")
info "Going to save new snapshot under ${timestamp}."

if [ -n "$ignore" ];
then
	info "Will ignore files matching $ignore."
fi

if [ -n "$ignore_file" ];
then
	info "Will ignore files listed in $ignore_file."
fi


# Look for previous snapshot
last_timestamp=$(ls -t | grep -v ".*\.log$" | tail -1)

# Prepare new snapshot
if [ -n "$last_timestamp" ];
then
    info "Found previous snapshot under ${last_timestamp}."    
    cp -al ${target}/${last_timestamp} ${target}/${timestamp}
else
    info "No previous snapshot found. Stating initial backup."
    mkdir -p ${target}/${timestamp}
fi

info "Starting backup at $(date)."

# And do the rsync
# --ignore-error might be a little risky here. Unfortunately some strange file 
# permissions keep rsync from deleting files.
rsync_opts="-vaz --delete --delete-excluded --ignore-errors"
if [ -n "$ignore" ];
then
	rsync_opts="$rsync_opts --exclude='${ignore}'"
fi

if [ -n "$ignore_file" ];
then
	rsync_opts="$rsync_opts --exclude-from='${ignore_file}'"
fi

rsync  ${rsync_opts} ${source} ${target}/${timestamp} > ${target}/${timestamp}.log 2>${target}/${timestamp}.log

info "Backup finished at $(date)."
info "Backup done."

